import { ElMessage, UploadRequestOptions } from "element-plus";
import { createAxios } from "~/api/util/request-wrapper";
import SparkMD5 from "spark-md5";
import { reactive } from "vue";
import { JsonResult } from "~/api/types";

const MAXSIZE = 1024 * 1024;

export class ImageApi {

  fileList: string[] = reactive<any>([]);
  img = reactive({
    src: undefined,
    value: undefined,
  });
  http = createAxios();
  token = localStorage.getItem("token");
  uploadState = reactive({
    action: "/file/img/upload",
    headers: { "Authorization": "Bearer " + this.token },
  });


  init() {
    this.fileList = reactive([]);
    this.img.src = undefined;
    this.img.value = undefined;
  }

  onSuccess(response: JsonResult<any>) {
    const _this = this;
    if (response.ok && response.data) {
      ElMessage.success("上传成功");

      const xhr = new XMLHttpRequest();
      xhr.open("GET", "/api" + response.data);
      xhr.setRequestHeader("Authorization", "Bearer " + this.token);
      xhr.responseType = "blob";
      xhr.onload = function() {
        const imgUrl: any = URL.createObjectURL(this.response);
        _this.fileList.push(imgUrl);
        _this.img.value = response.data;
        _this.img.src = imgUrl;
      };
      xhr.send();
    }
    return this.fileList;
  }

  getImg(path: string) {
    return new Promise((resolve) => {
      const xhr = new XMLHttpRequest();
      xhr.open("GET", "/api" + path);
      xhr.setRequestHeader("Authorization", "Bearer " + this.token);
      xhr.responseType = "blob";
      xhr.send();
      xhr.onload = function() {
        resolve(URL.createObjectURL(this.response));
      };
    });
  }

  async onHttpRequest({ file }: UploadRequestOptions, isPublic: boolean = true) {
    const md5: {
      md5: string,
      sliceMd5s: {
        currentChunk: number,
        md5: string,
      }[]
    } = await this.fileMd5(file);

    const formData = new FormData();
    formData.set("file", file);
    formData.set("md5", md5.md5);
    formData.set("isPublic", String(isPublic));
    formData.set("fileName", file.name);
    return await this.http.post(this.uploadState.action, formData, { headers: this.uploadState.headers });
  }

  fileMd5(file: Blob): Promise<any> {
    return new Promise(resolve => {
      let arr: any[] = [];
      let fileSize = 0;
      let blobSlice = File.prototype.slice || (File.prototype as any).mozSlice || (File.prototype as any).webkitSlice;
      const fileReader = new FileReader();
      const chunks = Math.ceil(file.size / MAXSIZE);
      let currentChunk = 0;

      //注意点，网上都是 这一步都是有问题的， SparkMD5.ArrayBuffer()
      const allSpark = new SparkMD5.ArrayBuffer();
      fileReader.onload = async function(e) {
        const spark = new SparkMD5.ArrayBuffer();
        allSpark.append((e.target?.result as ArrayBuffer));
        spark.append((e.target?.result as ArrayBuffer));
        const md5 = spark.end();
        currentChunk++;
        let obj = {
          currentChunk: currentChunk,
          md5: md5,
        };
        fileSize += ((e.target?.result as ArrayBuffer).byteLength);
        if (currentChunk < chunks) {
          arr.push(obj);
          loadNext();
        } else {
          arr.push(obj);
          resolve({
            md5: allSpark.end(),
            sliceMd5s: arr,
          });
        }
      };
      fileReader.onerror = function() {
        console.warn("FileReader error.");
      };

      function loadNext() {
        const start = currentChunk * MAXSIZE;
        const end = ((start + MAXSIZE) >= file.size) ? file.size : start + MAXSIZE;
        // 注意这里的 fileRaw
        fileReader.readAsArrayBuffer(blobSlice.call(file, start, end));
      }

      loadNext();
    });
  }
}
